/********************************************************
 * Filename: TclContentAssist.java
 * Author: LMU
 * Program: TUnit
 * Description: The content assist processor for TUnit.   
 * Revision History:
 * 20060517: Initial Revision.
 * 20060927: Updated findStartWith() for an offset of 0.
 * 20061009: Did a little refactoring.  Updated 
 * computeCompletionProposals to use a new method 
 * setCompletions to get the necessary completion 
 * proposals.  
 * *****************************************************/

package edu.lmu.cs.tUnit.editor;

import java.util.Vector;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;

import edu.lmu.cs.tUnit.log.TUnitLog;

public class TclContentAssist implements IContentAssistProcessor {

	/**
	 * Computes the completion proposals  
	 */
	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
		String start = findStartWith(viewer.getDocument(), offset);
		Vector v = new Vector();
		
		// string command
		if("string".equals(start)) { 
			setCompletions(v, "string ", TclContentAssistConstants.TclStringOptions, offset);
		}
		
		// string command
		else if("[string".equals(start)) { 
			setCompletions(v, "[string ", TclContentAssistConstants.TclStringOptions, offset);
		}
		
		// array command
		else if("array".equals(start)) {
			setCompletions(v, "array ", TclContentAssistConstants.TclArrayOptions, offset);
		}
		
		// array command
		else if("[array".equals(start)) {
			setCompletions(v, "[array ", TclContentAssistConstants.TclArrayOptions, offset);
		}
		
		// file command
		else if("file".equals(start)) {
			setCompletions(v, "file ", TclContentAssistConstants.TclFileOptions, offset);
		}
		
		// file command
		else if("[file".equals(start)) {
			setCompletions(v, "[file ", TclContentAssistConstants.TclFileOptions, offset);
		}
		
		// registry command
		else if("registry".equals(start)) {
			setCompletions(v, "registry ", TclContentAssistConstants.TclRegistryOptions, offset);
		}
		
		// registry command
		else if("[registry".equals(start)) {
			setCompletions(v, "[registry ", TclContentAssistConstants.TclRegistryOptions, offset);
		}
		
		// package command
		else if("package".equals(start)) {
			setCompletions(v, "package ", TclContentAssistConstants.TclPackageOptions, offset);
		}
		
		// package command
		else if("[package".equals(start)) {
			setCompletions(v, "[package ", TclContentAssistConstants.TclPackageOptions, offset);
		}
		
		// info command
		else if("info".equals(start)) {
			setCompletions(v, "info ", TclContentAssistConstants.TclInfoOptions, offset);
		}
		
		// info command
		else if("[info".equals(start)) {
			setCompletions(v, "[info ", TclContentAssistConstants.TclInfoOptions, offset);
		}
		
		// history command
		else if("history".equals(start)) {
			setCompletions(v, "history ", TclContentAssistConstants.TclHistoryOptions, offset);
		}
		
		// history command
		else if("[history".equals(start)) {
			setCompletions(v, "[history ", TclContentAssistConstants.TclHistoryOptions, offset);
		}

		// namespace command 
		else if("namespace".equals(start)) {
			setCompletions(v, "namespace ", TclContentAssistConstants.TclNamespaceOptions, offset);
		}
		
		// namespace command 
		else if("[namespace".equals(start)) {
			setCompletions(v, "[namespace ", TclContentAssistConstants.TclNamespaceOptions, offset);
		}
		
		// encoding command
		else if("encoding".equals(start)) {
			setCompletions(v, "encoding ", TclContentAssistConstants.TclEncodingOptions, offset);
		}
		
		// encoding command
		else if("[encoding".equals(start)) {
			setCompletions(v, "[encoding ", TclContentAssistConstants.TclEncodingOptions, offset);
		}

		// after command
		else if("after".equals(start)) {
			setCompletions(v, "after ", TclContentAssistConstants.TclAfterOptions, offset);
		}
		
		// after command
		else if("[after".equals(start)) {
			setCompletions(v, "[after ", TclContentAssistConstants.TclAfterOptions, offset);
		}
		
		// interp command
		else if("interp".equals(start)) {
			setCompletions(v, "interp ", TclContentAssistConstants.TclInterpOptions, offset);
		}
		
		// interp command
		else if("[interp".equals(start)) {
			setCompletions(v, "[interp ", TclContentAssistConstants.TclInterpOptions, offset);
		}
		
		// pack command
		else if("pack".equals(start)) {
			setCompletions(v, "pack ", TclContentAssistConstants.TclPackOptions, offset);
		}
		
		// pack command
		else if("[pack".equals(start)) {
			setCompletions(v, "[pack ", TclContentAssistConstants.TclPackOptions, offset);
		}
		
		// grid command
		else if("grid".equals(start)) {
			setCompletions(v, "grid ", TclContentAssistConstants.TclGridOptions, offset);
		}
		
		// grid command
		else if("[grid".equals(start)) {
			setCompletions(v, "[grid ", TclContentAssistConstants.TclGridOptions, offset);
		}
		
		// place command
		else if("place".equals(start)) {
			setCompletions(v, "place ", TclContentAssistConstants.TclPlaceOptions, offset);
		}
		
		// place command
		else if("[place".equals(start)) {
			setCompletions(v, "[place ", TclContentAssistConstants.TclPlaceOptions, offset);
		}
		
		// selection command
		else if("selection".equals(start)) {
			setCompletions(v, "selection ", TclContentAssistConstants.TclSelectionOptions, offset);
		}
		
		// selection command
		else if("[selection".equals(start)) {
			setCompletions(v, "[selection ", TclContentAssistConstants.TclSelectionOptions, offset);
		}
		
		// grab command
		else if("grab".equals(start)) {
			setCompletions(v, "grab ", TclContentAssistConstants.TclGrabOptions, offset);
		}
		
		// grab command
		else if("[grab".equals(start)) {
			setCompletions(v, "[grab ", TclContentAssistConstants.TclGrabOptions, offset);
		}
		
		// tkwait command
		else if("tkwait".equals(start)) {
			setCompletions(v, "tkwait ", TclContentAssistConstants.TclTkwaitOptions, offset);
		}
		
		// tkwait command
		else if("[tkwait".equals(start)) {
			setCompletions(v, "[tkwait ", TclContentAssistConstants.TclTkwaitOptions, offset);
		}
		
		// image command
		else if("image".equals(start)) {
			setCompletions(v, "image ", TclContentAssistConstants.TclImageOptions, offset);
		}
		
		// image command
		else if("[image".equals(start)) {
			setCompletions(v, "[image ", TclContentAssistConstants.TclImageOptions, offset);
		}
		
		// font command
		else if("font".equals(start)) {
			setCompletions(v, "font ", TclContentAssistConstants.TclFontOptions, offset);
		}
		
		// font command
		else if("[font".equals(start)) {
			setCompletions(v, "[font ", TclContentAssistConstants.TclFontOptions, offset);
		}
		
		// wm command
		else if("wm".equals(start)) {
			setCompletions(v, "wm ", TclContentAssistConstants.TclWmOptions, offset);
		}
		
		// wm command
		else if("[wm".equals(start)) {
			setCompletions(v, "[wm ", TclContentAssistConstants.TclWmOptions, offset);
		}

		// winfo command
		else if("winfo".equals(start)) {
			setCompletions(v, "winfo ", TclContentAssistConstants.TclWinfoOptions, offset);
		}
		
		// winfo command
		else if("[winfo".equals(start)) {
			setCompletions(v, "[winfo ", TclContentAssistConstants.TclWinfoOptions, offset);
		}

		// tk command
		else if("tk".equals(start)) {
			setCompletions(v, "tk ", TclContentAssistConstants.TclTkOptions, offset);
		}
		
		// tk command
		else if("[tk".equals(start)) {
			setCompletions(v, "[tk ", TclContentAssistConstants.TclTkOptions, offset);
		}
		
		// list command
		else if("l".equals(start)) {
			setCompletions(v, "", TclContentAssistConstants.TclListOptions, offset);
		}
		
		// list command
		else if("[l".equals(start)) {
			setCompletions(v, "[", TclContentAssistConstants.TclListOptions, offset);
		}
		
		ICompletionProposal[] result= new ICompletionProposal[v.size()];
		v.copyInto(result);
		return result;
	}
	
	/**
	 * Set the completions based on the string
	 * @param v vector to hold completions
	 * @param start the start string
	 * @param proposals the proposals
	 * @param offset1 offset in the document
	 * @param offset2 offset of whitespace and brackets
	 */
	public void setCompletions(Vector v, String start, String[] proposals, int offset) {
		int whitespace = 1;
		if("[".equals(start) || "".equals(start)) {
			whitespace = -1;
		}
		for(int i = 0; i < proposals.length; i++) {
			v.add(new CompletionProposal(start + proposals[i], 
		    	offset-(start.length()-whitespace), 
		    	start.length()-whitespace, 
		    	start.length() + proposals[i].length(), 
				null, 
				start + proposals[i], 
				null, 
				"")); 				
		}
	}

	public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
		return null;
	}

	/**
	 * Activate completion proposal for all lowercase letters
	 */
	public char[] getCompletionProposalAutoActivationCharacters() {
		return new char[] {
			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
			't', 'u', 'v', 'w', 'x', 'y', 'z', '['
		};
	}

	public char[] getContextInformationAutoActivationCharacters() {
		return null;
	}

	public String getErrorMessage() {
		return null;
	}

	public IContextInformationValidator getContextInformationValidator() {
		return null;
	}

	/**
	 * Check what the string starts with
	 * @param doc
	 * @param documentOffset
	 * @return
	 */
	private String findStartWith(IDocument doc, int documentOffset){
		if(documentOffset == 0) {
			return "";
		}
		
		StringBuffer buffer = new StringBuffer();
		int offset = documentOffset - 1;
		try{
			char c = doc.getChar(offset);
			while(offset >= 0 && (!Character.isWhitespace(c))){
				buffer.append(c);
				offset--;
				if(offset < 0) {
					break;
				}
				c = doc.getChar(offset);
			}
		} catch(BadLocationException e){
			TUnitLog.logError("Could not determine what the string starts with.", e);
		}
		return buffer.reverse().toString();
	}
}
